package com.codecademy.eventhub.web; import com.codecademy.eventhub.EventHub; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonSerializationContext; import com.google.gson.JsonSerializer; import com.google.inject.AbstractModule; import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Singleton; import com.codecademy.eventhub.base.KeyValueCallback; import com.codecademy.eventhub.index.DatedEventIndex; import com.codecademy.eventhub.index.PropertiesIndex; import com.codecademy.eventhub.index.ShardedEventIndex; import com.codecademy.eventhub.index.UserEventIndex; import com.codecademy.eventhub.model.Event; import com.codecademy.eventhub.model.User; import com.codecademy.eventhub.storage.BloomFilteredEventStorage; import com.codecademy.eventhub.storage.BloomFilteredUserStorage; import com.codecademy.eventhub.web.commands.Command; import com.codecademy.eventhub.web.commands.Path; import org.reflections.Reflections; import javax.inject.Named; import javax.inject.Provider; import java.lang.reflect.Type; import java.util.Map; import java.util.Set; public class Module extends AbstractModule { private static final String PACKAGE_NAME = "com.codecademy.eventhub.web.commands"; @Override protected void configure() {} @Provides private Gson getGson() { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.setPrettyPrinting(); gsonBuilder.registerTypeAdapter(User.class, new UserJsonSerializer()); gsonBuilder.registerTypeAdapter(Event.class, new EventJsonSerializer()); return gsonBuilder.create(); } @Provides @Singleton public EventHub getEventHub( @Named("eventhub.directory") String directory, ShardedEventIndex shardedEventIndex, DatedEventIndex datedEventIndex, PropertiesIndex propertiesIndex, UserEventIndex userEventIndex, BloomFilteredEventStorage eventStorage, BloomFilteredUserStorage userStorage) { return new EventHub(directory, shardedEventIndex, datedEventIndex, propertiesIndex, userEventIndex, eventStorage, userStorage); } @Provides private EventHubHandler getEventHubHandler(Injector injector, EventHub eventHub) throws ClassNotFoundException { Map<String, Provider<Command>> commandsMap = Maps.newHashMap(); Reflections reflections = new Reflections(PACKAGE_NAME); Set<Class<? extends Command>> commandClasses = reflections.getSubTypesOf(Command.class); for (Class<? extends Command> commandClass : commandClasses) { String path = commandClass.getAnnotation(Path.class).value(); //noinspection unchecked commandsMap.put(path, (Provider<Command>) injector.getProvider(commandClass)); } return new EventHubHandler(eventHub, commandsMap); } private static class UserJsonSerializer implements JsonSerializer<User> { @Override public JsonElement serialize(User user, Type type, JsonSerializationContext jsonSerializationContext) { final JsonObject jsonObject = new JsonObject(); user.enumerate(new KeyValueCallback() { @Override public void callback(String key, String value) { jsonObject.addProperty(key, value); } }); return jsonObject; } } private static class EventJsonSerializer implements JsonSerializer<Event> { @Override public JsonElement serialize(Event event, Type type, JsonSerializationContext jsonSerializationContext) { final JsonObject jsonObject = new JsonObject(); event.enumerate(new KeyValueCallback() { @Override public void callback(String key, String value) { jsonObject.addProperty(key, value); } }); return jsonObject; } } }